package org.dei.perla.sys.console;



import java.net.Socket;

import org.dei.perla.parser.statements.Query;
import org.dei.perla.sys.console.messages.ConsoleMessage.PerLaRequest;
import org.dei.perla.sys.console.ConsoleUtils;
import org.dei.perla.sys.core.QueryParserStatic;
import org.dei.perla.utils.pipe.Pipe;

/**
 * Per ogni richiesta di connessione viene generato un Thread
 * rappresentato da questa classe.
 * @author diego
 */
class ServerThread extends Thread {

	/**
	 * Il socket che verra' usato per la connessione
	 */
	private Socket pSocket;
	private Pipe<String> pipe;
		
	/**
	 * Costruttore
	 * @param parSocket
	 * @param pipe 
	 */
	ServerThread(Socket parSocket, Pipe<String> pipe) {
		this.pSocket = parSocket;
		this.pipe = pipe;
	}
	
	/**
	 * Metodo per far partire l'attivita' 
	 */
	public void run() {
		
		boolean tConnectionOpened = true;
		
		try {
			
			//...fino a quando non arriva il segnale di connessione da terminare...
			while (tConnectionOpened) {					
				
				//...Ricevo la richiesta...
				PerLaRequest tRequest = ConsoleUtils.receiveRequest(pSocket);								
				if (!tRequest.isInitialized()) {
					System.out.println("Error Parsing message \n");
				}
				else{
				//Recupero l'header e agisco di conseguenza
					switch (tRequest.getRequestHeader()) {
						case TEST_QUERY : {
							String query = tRequest.getInjectQueryRequestMessage().getQueryToInject();
							if( QueryParserStatic.isValid(query) == false){
								ConsoleUtils.injectCommandResponse(this.pSocket, "error parsing query");
							}
							else{
								ConsoleUtils.injectCommandResponse(this.pSocket, "parsing query success");
							}
							break;
						}
						case STOP_QUERY : {
							tConnectionOpened = false;			
							break;
						}
						case SHOW_VERSION : {
							ConsoleUtils.versionCommandResponse(this.pSocket);
							break;
						}
						case INSPECT_COMMAND:{
							System.out.println("Received INSPECT_COMMAND");
							ConsoleUtils.inspectResponse(this.pSocket, tRequest.getInspectRequestMessage().getAgentId());
							break;
						}
						case INJECT_QUERY : {
							String query = tRequest.getInjectQueryRequestMessage().getQueryToInject();
							Query parsedQuery = QueryParserStatic.parse(query);
							
							if(parsedQuery == null){
								ConsoleUtils.injectCommandResponse(this.pSocket, "error parsing query");
							}
							else{
								ConsoleUtils.injectCommandResponse(this.pSocket, "parsing query success");
							}
							break;
						}
						case INJECT_XML : {
							String xmlString = tRequest.getInjectXmlRequestMessage().getXmlToInject();
							this.pipe.enqueue(xmlString);
							break;
						}
						default:{
							break;
						}
					}
				}
				//..controllo che il client non abbia chiuso la connessione, altrimenti termino			
				if (!this.pSocket.isConnected()) 
					tConnectionOpened = false;	
			}
	
		} catch (Exception e) {
			System.out.println("Errore nel server");
			e.printStackTrace();
		}
		
		//...qui la connessione e' stata chiusa, agisco di conseguenza.
		try {
			this.finalize();		
		} catch (Throwable e) {
			System.out.println("Errore nella chiusura del server...\n");		
		}
		System.out.println("Questo ServerThread ha terminato, addio....\n");
		
	}
}
